package com.shg.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;

import com.shg.bean.Book;
import com.shg.bean.QueryResult;
import com.shg.service.BasiceDao;

@SuppressWarnings("unchecked")
public class BasiceDaoImpl<E> implements BasiceDao<E> {

	@Resource
	protected SessionFactory  sessionFactory;
	
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	/**
	 * 将一个实体对象保存进入数据库种
	 * @param entity 实体对象
	 */
	public void insert(E entity) {
		sessionFactory.getCurrentSession().save(entity);
	}
	/**
	 * 根据ID删除数据库表种的一条记录
	 * @param entity 将要删除的实体类
	 * @param id 改实体对象对应的ID字段（因为并不是每一个表的ID名称字段都是id所以改字段作为参数传递进来）
	 * @param id_value ID对应的值
	 */
	public void delete(Class<Object> entity,String id,String id_value) {
		String hsql="delete from "+entity.getSimpleName()+" where "+id+"=:id";
		sessionFactory.getCurrentSession().createQuery(hsql)
											.setString("id", id_value)
											.executeUpdate();
	}
	/**
	 * 更新一个实体对象
	 * @param 实体对象
	 */
	public void update(E entity) {
		sessionFactory.getCurrentSession().merge(entity);
	}
	/**
	 *根据ID来获取一条记录
	 *@param entity实体对象
	 *@param entityID ID名称
	 */
	public Object select(Class entity,Serializable entityID) {
		return sessionFactory.getCurrentSession().get(entity,entityID);
	}
	/**
	 * 改方法查询所有的记录信息，并将查询得到结果按照拍下方式显示出来
	 * @param entity 查询的实体对象
	 * @param orderby order by子句
	 * @return
	 */
	public QueryResult<E> getPagination(Class<E> entity,LinkedHashMap<String, String> orderby){
		return getPagination(entity,-1,-1,null,null,orderby);
	}
	/**
	 * 分页查询，但是不排序,也没有条件
	 * @param entity 查询的实体对象
	 * @param firstResult 查询的起始索引位置
	 * @param maxResult 查询每一页显示的记录数
	 * @return
	 */
	public QueryResult<E> getPagination(Class<E> entity,int firstResult,int maxResult){
		return getPagination(entity,firstResult,maxResult,null,null,null); 
	}
	/**
	 * 分页查询，排序
	 * @param entity 查询的实体对象
	 * @param firstResult 查询的起始索引位置
	 * @param maxResult 查询每一页显示的记录数
	 * @param orderby 排序方式
	 * @return
	 */
	public QueryResult<E> getPagination(Class<E> entity,int firstResult,int maxResult,LinkedHashMap<String, String> orderby){
		return getPagination(entity, firstResult, maxResult, null, null, orderby);
	}
	/**
	 * 根据条件分页查询，但是不排序
	 * @param entity 查询的实体对象
	 * @param firstResult 查询的起始索引位置
	 * @param maxResult 查询每一页显示的记录数
	 * @param whereSQL 查询的条件
	 * @param parameters 查询条件的值
	 * @return
	 */
	public QueryResult<E> getPagination(Class<E> entity,int firstResult,int maxResult,
			String whereSQL,Object[] parameters){
		return getPagination(entity,firstResult,maxResult,whereSQL,parameters,null);
	}
	/**
	 * 根据条件分页查询，但是不排序
	 * @param entity 查询的实体对象
	 * @param firstResult 查询的起始索引位置
	 * @param maxResult 查询每一页显示的记录数
	 * @param whereSQL 查询的条件
	 * @return
	 */
	public QueryResult<E> getPagination(Class<E> entity,int firstResult,int maxResult,String whereSQL){
		return getPagination(entity,firstResult,maxResult,whereSQL,null,null);
	}
	/**
	 * 查询数据记录信息
	 * @param entity 将要查询的实体对象
	 * @param firstResult 开始查询的索引位置
	 * @param maxResult 每一页显示的数据记录信息
	 * @param whereSQL where条件部分 （如：id=? and name like ? and price<?）
	 * @param parameters 参数值数值（如{"XXXXXX","JAVA%",23.23}）
	 * @param orderby order by 子句的组成部分
	 */
	public QueryResult<E> getPagination(Class<E> entity,int firstResult,int maxResult,
			String whereSQL,Object[] parameters,LinkedHashMap<String, String> orderby) {
		//创建该对象用于接收查询结果，其中该对象的一个属性是存储用户的信息，另一是存储查询满足条件的所有结果记录数
		QueryResult<E> list=new QueryResult<E>();
		//当用户不需要where作为条件查询的时候将将传递进来的whereSQL设置为空字符串，否则不改变whereSQL的语句
		String where =  (whereSQL==null ||"".equals(whereSQL.trim()))?"":(" where "+whereSQL);
		Query query = sessionFactory.getCurrentSession().createQuery("from "+entity.getSimpleName()+where+buildSQL(orderby));
		setQueryParameter(query,parameters);									
		if(firstResult!=-1 && maxResult!=-1)
			query.setFirstResult(firstResult).setMaxResults(maxResult);
		list.setResultList(query.list());
		//统计总记录数
		query =sessionFactory.getCurrentSession().createQuery("select  count(*) from "+entity.getSimpleName()+where);
		setQueryParameter(query,parameters);
		list.setResultCount((Long)query.uniqueResult());
		return list;
	}
	/**
	 * 如果用户要求对查询出来的数据是按照某种顺序显示的话就在这个位置
	 * 对组装order by子句
	 * @param orderby
	 * @return
	 */
	protected static String buildSQL(LinkedHashMap<String, String> orderby){
		StringBuffer order=new StringBuffer("");;
		if(orderby!=null && !orderby.isEmpty()){
			order.append(" order by ");
			for(String key:orderby.keySet()){
				String value  = orderby.get(key);
				order.append(key+" "+value+",");
			}
			order.deleteCharAt(order.length()-1);
		}
		return order.toString();
	}
	/**
	 * 这里给组装好得HSQL的参数赋值，例如：from Person where age=? and sex=?
	 * @param query
	 * @param parameters
	 */
	private static void setQueryParameter(Query query,Object[] parameters){
		if(parameters!=null && parameters.length>0){
			for(int i=0;i<parameters.length;i++){
				query.setParameter(i, parameters[i]);
			}
		}
	}
	
	/**
	 * 
	 */
	public Long getTotal(Class<E> entity,String whereSQL,Object[] parameters) {
		String where =  (whereSQL==null ||"".equals(whereSQL.trim()))?"":" where "+whereSQL;
		Query query= sessionFactory.getCurrentSession().createQuery("select  count(*) from "+entity.getSimpleName()+where);
		setQueryParameter(query,parameters);
		Long total =(Long) query.uniqueResult();
		return total;
	}
	/**
	 * 统计数据
	 * @param shopId 店铺的ID
	 * @param maxResult 返回的最大记录数
	 * @param entity 查询的实体对象
	 * @return
	 */
	public List<Book> getStat(String shopId,int maxResult,Class<E> entity){
		List<Book>  list=new ArrayList<Book>();
		//首先查询出该店铺的销售的所有书籍
		String sql=null;
		if(shopId==null){
			sql="from "+Book.class.getSimpleName()+" where shows=1";
		}else{
			sql="from "+Book.class.getSimpleName()+" where shop_id='"+shopId+"' and shows=1";
		}
		
		List<Book> books = sessionFactory.getCurrentSession().createQuery(sql).list();
		//然后查询这些书籍当中曾经售出过的，拿出前10条
		if(books.size()>0){
			Criteria criteria= sessionFactory.getCurrentSession().createCriteria(entity)
			.setProjection(Projections.projectionList()
							.add(Projections.rowCount(),"myRowCount")
							.add(Projections.groupProperty("book"))
						  ).add(Property.forName("book").in(books))
			.addOrder(Order.desc("myRowCount"))
			.setFirstResult(0)
			.setMaxResults(maxResult);
			List<Object> objectList = criteria.list();
			//查询出来来的是List数组 而数组里面又包含数组
			for(Object parentList:objectList){
				Object[] childList=(Object[]) parentList;
				//1、获取Book对象
				Book book=null;
				for(Object object:childList){
					if(object instanceof Book){
						book=(Book)object;
					}
				}
				
				if(book!=null){
					//获取销售出去的总记录数
					for(Object object:childList){
						if(!(object instanceof Book)){
							book.setRecord((Long) object);
						}
					}
					list.add(book);
				}
			}
		}
		return list;
	}
	
}
